package model.scaling;

import java.util.ArrayList;
import java.util.List;

import model.auxillary.Parameter;
import model.auxillary.ParameterCollectionScaling;
import model.auxillary.ParameterListScaling.ParameterType;

//#Neu
/**
* A {@code Product} is part of the scaling. It allows calculations of 
* relative energy efficiencies of a product.
* @author Sebastian Perlwitz
*
*/
public class Product extends Scaling implements IProduct {
	
	/**
	 * The rank of this {@code Product}. It is used to give parameters a 
	 * unique abbreviation.
	 */
	private int rank;
	
	/**
	 * A List that holds every factory in which this product is produced.
	 */
	private ArrayList<IFactory> factories;
	
	/**
	 * To create a new {@code Product}.
	 * @param name the name of the product.
	 * @param id a unique idea that identifies this product.
	 * @param rank the rank of this product.
	 */
	public Product(
			String name,
			String id,
			int rank) {
		super(name, id);
		this.rank = rank;
		factories = new ArrayList<IFactory>();
		addParameters();
	}
	
	@Override
	public void addFactory(IFactory factory) {
 		factories.add(factory);
 	}
	
	@Override
	public void removeAllFactoriesOfProduct() {
		factories.clear();
	}
	
	@Override
	public ArrayList<IFactory> getFactories() {
		return factories;
	}
	
	/**
	 * To add the products' defining parameters.
     */
	private void addParameters(){
		List<Parameter> newParams = new ArrayList<Parameter>();
		
		newParams.add(new Parameter(
				"Relative Energieeffizienz",
				"REE4_Produkt," + rank,
				"<html>REE<sub>Produkt, " + rank + "</sub></html>",
				"<html>[%]</html>",
				false,
				this));
		
		parameters.addScalingParameters(
				ParameterType.PRODUCT_RESULT_PARAMETER, newParams);
	}

	@Override
	public void calculate() {
		
		error = false;
    	aborted = false;
    	
    	// Calculation of REE4_Produkt (Formel 37.1).
    	double Zaehler = 0.0;
    	double Nenner = 0.0;
    	
    	for(IFactory factory : factories) {
    		double N_ProduktWerk = factory.getParameter("N_ProduktWerk", 
    				ParameterType.FACTORY_PARAMETER).getValue();
    		double MF_ProduktWerk = factory.getParameter("MF_ProduktWerk", 
    				ParameterType.FACTORY_PARAMETER).getValue();
    		double REE3_ProduktWerk = factory.getParameter("REE3_ProduktWerk", 
    				ParameterType.INTERIM_RESULT_PARAMETER).getValue();
    		
    		// Change unit of REE3_ProduktWerk from [%] to [1].
    		REE3_ProduktWerk /= 100;
    		
    		Zaehler += (REE3_ProduktWerk * MF_ProduktWerk * N_ProduktWerk);
    		Nenner += (MF_ProduktWerk * N_ProduktWerk);
    	}
    	
    	double REE4_Produkt = Zaehler / Nenner; // [1]
    	REE4_Produkt *= 100; // [%]
    	getParameter("REE4_Produkt", 
				ParameterType.PRODUCT_RESULT_PARAMETER).setValue(REE4_Produkt);
	}
	
	@Override
	public boolean aborted() {
		return aborted;
	}

	@Override
	public boolean getError() {
		return error;
	}
	
	@Override
	public Parameter getParameter(String abbreviation, ParameterType type) {

		// An example: To find the parameter 'f_lambda,1' by searching for
		// 'f_lambda'.
		String a = abbreviation + "_" + rank;
		String b = abbreviation + "," + rank;
		Parameter paramA = parameters.getParameter(type, a);
		Parameter paramB = parameters.getParameter(type, b);
		if(paramA == null) {
			return paramB;
		} else {
			return paramA;
		}
	}

	@Override
	public List<ParameterCollectionScaling> getResults() {
		List<ParameterCollectionScaling> results =
				new ArrayList<ParameterCollectionScaling>();
		results.add(parameters.getParameterCollection(
				ParameterType.PRODUCT_RESULT_PARAMETER));
		return results;
	}

}
